#include "mid_can.h"
#include "CanIf.h"
#include "CanIf_Cbk.h"
#include "app_can.h"
#include "app_upgrade.h"



struct_CanBusoff_t g_canBusoff[2];

// 配置RxFIFO接收必须使用该结构体声明的变量
static flexcan_msgbuff_t recvMsgCan0;

/* Private variables ---------------------------------------------------------*/
CAN_Type * const g_canBase[] = { CAN0, CAN1, CAN2};
can_state_t * g_canStatePtr[CAN_INSTANCE_COUNT] = { NULL };
void FLEXCAN_IRQHandler(uint8_t instance);
void CANBusResetEsr(uint8_t instance);
static uint8_t CANIsRxBuffFull(uint8_t instance);

static void CANx_ISREvent(uint8_t instance, 
                      flexcan_event_type_t eventType,
                      uint32_t buffIdx, 
                      flexcan_state_t *flexcanState)
{
	can_state_t *canState = g_canStatePtr[instance];
	struct_canMsg_t *canRx = &canState->rxBuff[canState->rxInPtr];

	if(instance == INST_CAN0COM){
		if((eventType == FLEXCAN_EVENT_RXFIFO_COMPLETE) || (eventType == FLEXCAN_EVENT_RX_COMPLETE)){
			canRx->Id = recvMsgCan0.msgId;
			canRx->Dlc = recvMsgCan0.dataLen;
			memcpy(canRx->Data, recvMsgCan0.data,8);
			if(CANIsRxBuffFull(instance) == FALSE)
			{
				canState->rxInPtr++;
				if(canState->rxInPtr >= canState->rxBuffSize)canState->rxInPtr = 0;
			}
			FLEXCAN_DRV_RxFifo(INST_CAN0COM, &recvMsgCan0);
		} 
		if(eventType == FLEXCAN_EVENT_TX_COMPLETE){
			canState->isTxBusy = False;
		}
	}
}
void  ConfigCanidFilter(uint8_t instance,flexcan_id_table_t* dataInfo)
{
	switch(instance)
	{
		case INST_CAN0COM :
			dataInfo->isRemoteFrame = false,//true,
			dataInfo->isExtendedFrame = false,
			dataInfo->idFilter = sg_can0FilterMaskIdList;
			break;
//		case INST_CAN1COM :
//			dataInfo->isRemoteFrame = false,//true,
//			dataInfo->isExtendedFrame = false,
//			dataInfo->idFilter = sg_can1FilterMaskIdList;
//			break;
//		case INST_CAN2COM:
//			break;
		default:
			break;
	}
}

void CANInit(uint8_t instance)
{
	status_t rc = STATUS_ERROR;
	flexcan_id_table_t  id_filter_table;
	//配置PIN脚
	if(CAN0CH == instance)
	{
		/* Configure Pin for CAN TX */
		PCC->PCCn[PCC_PORTC_INDEX ] |= PCC_PCCn_CGC_MASK; /* Enable clock for PORTC */
		PORTC->PCR[2] |= PORT_PCR_MUX(3) | PORT_PCR_PS(1) | PORT_PCR_PE(1); /* Port C2: MUX = CAN0_RX,CAN0 RX */
		PORTC->PCR[3] |= PORT_PCR_MUX(3) | PORT_PCR_PS(1) | PORT_PCR_PE(1); /* Port C3: MUX = CAN0_TX,CAN0 TX */
		PCC->PCCn[PCC_FlexCAN0_INDEX] |= PCC_PCCn_CGC_MASK;/* CGC=1: enable clock to FlexCAN0 */
		rc = FLEXCAN_DRV_Init(INST_CAN0COM, &can0Com_State, &can0Com_InitConfig0);
		if ( STATUS_SUCCESS == rc )
        {
			ConfigCanidFilter(INST_CAN0COM, &id_filter_table);
			FLEXCAN_DRV_ConfigRxFifo(INST_CAN0COM, FLEXCAN_RX_FIFO_ID_FORMAT_A, &id_filter_table);
			FLEXCAN_DRV_SetRxFifoGlobalMask(INST_CAN0COM,FLEXCAN_MSG_ID_STD,0x7ff);
			// FLEXCAN_DRV_SetRxFifoGlobalMask(instance,FLEXCAN_MSG_ID_EXT,0x1FFFFFFF);
			// FLEXCAN_SetRxFifoFilterRang(INST_CAN0COM, data->num_id_filters, 0x500,0x540);
            /* 设置CAN相关中断 */
            INT_SYS_SetPriority( CAN0_Error_IRQn + (instance * 7),         INT_PRIORITY_OF_CAN0_ERROR_IRQ );
            INT_SYS_SetPriority( CAN0_ORed_IRQn + (instance * 7),          INT_PRIORITY_OF_CAN0_ORED_IRQ );
            INT_SYS_SetPriority( CAN0_ORed_0_15_MB_IRQn + (instance * 7),  INT_PRIORITY_OF_CAN0_ORED_0_15_MB_IRQ );

            FLEXCAN_DRV_InstallEventCallback(INST_CAN0COM, CANx_ISREvent, NULL );
            // FLEXCAN_DRV_InstallErrorCallback( instance, pCallback_error, NULL );

			// Start receiving data in RX_RXFIFO.
			FLEXCAN_DRV_RxFifo(INST_CAN0COM, &recvMsgCan0);

			// Start receiving data in RX_MAILBOX. 
			// FLEXCAN_DRV_Receive()
        }
	}
	else if(CAN1CH == instance)
	{
		// PCC->PCCn[PCC_PORTA_INDEX ] |= PCC_PCCn_CGC_MASK; /* Enable clock for PORTA */
		// PORTA->PCR[12] = PORT_PCR_MUX(3) | PORT_PCR_PS(1) | PORT_PCR_PE(1);/* CAN1 RX */
		// PORTA->PCR[13] = PORT_PCR_MUX(3) | PORT_PCR_PS(1) | PORT_PCR_PE(1);/* CAN1 TX */
		// FLEXCAN_DRV_Init(INST_CAN1COM, &can1Com_State, &can1Com_InitConfig0);
	}
	else if(CAN2CH == instance)
	{
		//PORTC->PCR[17] |= 0X303 ;
		//PORTC->PCR[16] |= 0X303 ;
	}
}


/*************************************************************************
*  函数名称：CANSendData
*  功能说明：发送数据
*  参数说明：CANChannel：模块号         
//          iMB：缓冲区号
//	    id: ID号
//          length：数据长度
//	    Data[8]:发送数据缓冲区
*  函数返回：0：成功，1：失败
*************************************************************************/
uint8_t CANSendData(uint8_t instance, const struct_canMsg_t *pCanMsg)
{
	CAN_Type * base = g_canBase[instance];
	uint8_t numOfFilters;
	uint8_t mb_idx;
	flexcan_data_info_t tx_info;
	uint8_t data[8] = {0};
	uint32_t canid = pCanMsg->Id;
	uint8_t ret=0;

	numOfFilters = (((base->CTRL2) & CAN_CTRL2_RFFN_MASK) >> CAN_CTRL2_RFFN_SHIFT);
	mb_idx = numOfFilters*2+8;
	// mb_idx = 10;
	tx_info.msg_id_type = (flexcan_msgbuff_id_type_t)pCanMsg->IdType; 
	tx_info.data_length= pCanMsg->Dlc; 
	tx_info.fd_enable= false; 
	tx_info.fd_padding= 0; 
	tx_info.enable_brs= false; 
	tx_info.is_remote= false; 
	memset(data,0,8);
	memcpy(data,(uint8_t*)&pCanMsg->Data[0],pCanMsg->Dlc);
	FLEXCAN_DRV_ConfigTxMb(instance, mb_idx, &tx_info, canid);
	ret = FLEXCAN_DRV_Send(instance, mb_idx, &tx_info, canid, data);
    return ret;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : canIsRxBuffFull
 * Description   :
 *
 *END**************************************************************************/
static uint8_t CANIsRxBuffFull(uint8_t instance)
{
	uint16_t	u16Temp;
	uint8_t		res;
	can_state_t *canState = g_canStatePtr[instance];

	u16Temp = canState->rxInPtr;
	u16Temp++;
	if(u16Temp >= canState->rxBuffSize)u16Temp = 0;
	if(u16Temp == canState->rxOutPtr)
		res = TRUE;
	else
		res = FALSE;

	return res;
}


void CANWakeUpHandler(uint8_t instance)
{
	uint8_t i = 0, matchnum =0;
	can_state_t *canState = g_canStatePtr[instance];
	CAN_Type * base = g_canBase[instance];
	uint32_t flag = base->WU_MTC;
	matchnum = ((flag >> 8) & 0x000000FFu);
	if(canState->wakeUpCallBack != NULL)
	{
		if ((flag & CAN_WU_MTC_WUMF_MASK) != 0U)
        {
            base->WU_MTC |= CAN_WU_MTC_WUMF_MASK;
			for(i = 0; i < matchnum; i++)
			{
            	// canState->wakeUpCallBack(instance, i);
			}
        }
	}
}

void CANBusResetEsr(uint8_t instance)
{
	CAN_Type * base = g_canBase[instance];
	uint32_t ers = base->ESR1;

	base->ESR1 = ers;
	if(ers & 0x07)/*!< Masks for wakeup, error, bus off*/
	{
		base->ESR1 |= 0x07;/*!< Masks for wakeup, error, bus off*/
	}
}

void CANDisable(CAN_Type * base)
{
	uint16_t i = 0;
    /* To access the memory mapped registers */
    /* Entre disable mode (hard reset). */
    if(((base->MCR & CAN_MCR_MDIS_MASK) >> CAN_MCR_MDIS_SHIFT) == 0U)
    {
        /* Clock disable (module) */
        base->MCR = (base->MCR & ~CAN_MCR_MDIS_MASK) | CAN_MCR_MDIS(1U);

        /* Wait until disable mode acknowledged */
        while (((base->MCR & CAN_MCR_LPMACK_MASK) >> CAN_MCR_LPMACK_SHIFT) == 0U) 
		{
			i++;
			if(i >1000) break;
		}
    }
}
/*FUNCTION**********************************************************************
 *
 * Function Name : Can_AbortTransfer
 * Description   :
 *
 *END**************************************************************************/
void CANAbortTransfer(uint8_t instance)
{
	can_state_t *canState = g_canStatePtr[instance];
	//const can_user_config_t *can_Config = &can0_InitConfig;
	//CAN_Type * base = g_canBase[instance];

	canState->txInPtr = 0;
	canState->txOutPtr = 0;
}

void CAN0_ORed_IRQHandler(void)
{
	uint32_t dummy;
	dummy = dummy;
	dummy =CAN0->TIMER;             				/* Read TIMER to unlock message buffers */
}
void CAN0_Error_IRQHandler(void)
{
	uint32_t dummy;
	dummy = dummy;

	dummy =CAN0->TIMER;             				/* Read TIMER to unlock message buffers */
}
void CAN0_Wake_Up_IRQHandler(void)
{
	CANWakeUpHandler(CAN0CH);
	// FLEXCAN_WakeUpHandler(0U);
}
void CAN0_ORed_0_15_MB_IRQHandler(void)
{
	// CANIrqHandlerEvent(CAN0CH);
	FLEXCAN_IRQHandler(0U);
}

void CAN1_ORed_IRQHandler(void)
{
	uint32_t dummy;
	dummy = dummy;
	dummy =CAN1->TIMER;             				/* Read TIMER to unlock message buffers */
}
void CAN1_Error_IRQHandler(void)
{
	uint32_t dummy;
	dummy = dummy;

	dummy =CAN1->TIMER;             				/* Read TIMER to unlock message buffers */
}
void CAN1_ORed_0_15_MB_IRQHandler(void)
{
	FLEXCAN_IRQHandler(1U);
}

void CAN2_ORed_IRQHandler(void)
{
	uint32_t dummy;
	dummy = dummy;
	dummy =CAN2->TIMER;             				/* Read TIMER to unlock message buffers */
}
void CAN2_Error_IRQHandler(void)
{
	uint32_t dummy;
	dummy = dummy;

	dummy =CAN2->TIMER;             				/* Read TIMER to unlock message buffers */
}
void CAN2_ORed_0_15_MB_IRQHandler(void)
{
	FLEXCAN_IRQHandler(2U);
}

void mid_canVirtualRxCanMsg(uint8_t instance,uint32_t CanId, uint8_t dlc, uint8_t *data)
{
	can_state_t *canState = g_canStatePtr[instance];
	struct_canMsg_t *canRx = &canState->rxBuff[canState->rxInPtr];

	canRx->Id = CanId;
	canRx->Dlc = dlc;
	memcpy(canRx->Data, data, dlc);
	if(CANIsRxBuffFull(instance) == FALSE)
	{
		canState->rxInPtr++;
		if(canState->rxInPtr >= canState->rxBuffSize)canState->rxInPtr = 0;
	}
}
/*FUNCTION**********************************************************************
 *
 * Function Name : mid_canWrite
 * Description   :
 *
 *END**************************************************************************/
Enum_Result_t  mid_canWrite(uint8_t instance, const struct_canMsg_t *canMsg)
{
	can_state_t *canState = g_canStatePtr[instance];

	uint32_t u32Index = canState->txInPtr;
	u32Index++;
	if(u32Index >= canState->txBuffSize)u32Index = 0;

	if(u32Index == canState->txOutPtr)
	{
		/* no free space for save */
		return E_MSGFULL;
	}

	struct_canMsg_t *pCanTxMsg = &canState->txBuff[canState->txInPtr];
	*pCanTxMsg = *canMsg;

	canState->txInPtr++;
	if(canState->txInPtr >= canState->txBuffSize)canState->txInPtr = 0;
	return E_OK;
}
/*FUNCTION**********************************************************************
 *
 * Function Name : mid_canTxService
 * Description   :
 *
 *END**************************************************************************/
extern void FLEXCAN_CompleteTransfer(uint8_t instance, uint32_t mb_idx);
void mid_canTimeout1ms(uint8_t instance)
{
	can_state_t *canState = g_canStatePtr[instance];
	CAN_Type * base = g_canBase[instance];
	uint8_t numOfFilters;
	uint8_t mb_idx;
	if(canState->isTxBusy == True){
		if(canState->txPendingTimeLeft >0) {
			canState->txPendingTimeLeft--;
		} else {
			canState->isTxBusy = False;
			numOfFilters = (((base->CTRL2) & CAN_CTRL2_RFFN_MASK) >> CAN_CTRL2_RFFN_SHIFT);
			mb_idx = numOfFilters*2+8;
			FLEXCAN_CompleteTransfer(instance, mb_idx);
		}
	}
}

Enum_Result_t mid_canTxService( uint8_t instance )
{
	can_state_t *canState = g_canStatePtr[instance];
	Enum_Result_t res = E_NOMSG;
	uint32_t ret = 0;
	/* check transmitter Buffer of CAN */
	if(canState->isTxBusy == True){
		return E_NOT_OK;
	}
	
	if(canState->txInPtr != canState->txOutPtr)
	{
		struct_canMsg_t *pCanTxMsg = &canState->txBuff[canState->txOutPtr];
		canState->isTxBusy = True;
		canState->txPendingTimeLeft = 100;
		ret = CANSendData(instance, pCanTxMsg);
		if(ret==0)
		{
			canState->txOutPtr++;
			if(canState->txOutPtr >= canState->txBuffSize)
			{
				canState->txOutPtr = 0;
			}
			res = E_OK;
		}
		else{
			res = E_NOT_OK;
		}
	}
	else
	{
		res = E_NOMSG;
	}
	return res;
}
/*FUNCTION**********************************************************************
 *
 * Function Name : CAN_RxIndication
 * Description   : 
 *
 *END**************************************************************************/
Enum_Result_t mid_canRxIndication( uint8_t instance )
{
	can_state_t *canState = g_canStatePtr[instance];
	Enum_Result_t  ret;

	if(canState->rxInPtr != canState->rxOutPtr)
	{
		struct_canMsg_t *canRx = &canState->rxBuff[canState->rxOutPtr];
		CanIf_RxIndication((Can_IdType)canRx->Id, canRx->Dlc, &canRx->Data[0]);
		canState->rxOutPtr++;
		if(canState->rxOutPtr >= canState->rxBuffSize)canState->rxOutPtr = 0;
	    ret = E_OK;
	}
	else
    {
        ret = E_NODATA;
	}

	return  ret;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : mid_CanWakeUp
 * Description   : Wake up for CAN.
 *
 *END**************************************************************************/
void mid_CanWakeUp(uint8_t instance)
{
	can_state_t *canState = g_canStatePtr[instance];
	CAN_Type * base = g_canBase[instance];
	
	base = base;
	if(canState->workState != CAN_OPERATING_WORKING)
	{
		canState->workState = CAN_OPERATING_WORKING;
//		can_log(ELOG_Trace, "[CAN%d]WakeUp!\n", instance);
	}
	CanIf_SetPduMode(CANIF_SET_ONLINE);
	//CAN_DISABLE_WAKEUP(base);
}
void mid_can_Init(uint8_t instance, can_state_t *state, const can_user_config_t *data)
{
	ASSERT(instance < CAN_INSTANCE_COUNT);

	if(state->workState != CAN_OPERATING_UNINIT)return;

	memset(( char* )state, 0U, sizeof( can_state_t ) ); 
	state->rxCallBack = data->rxCallBack;
	state->rxBuff = data->rxBuff;
	state->rxBuffSize = data->rxBuffSize;
	
	state->txCallBack = data->txCallBack;
	state->txBuff = data->txBuff;
	state->txBuffSize = data->txBuffSize;
	state->isTxBusy = False;

	state->wakeUpCallBack = data->wakeUpCallBack;
	//state->busOffCallBack = data->busOffCallBack;
	state->busOffCallBack = NULL;
	state->workState = CAN_OPERATING_WORKING;
	state->CommunicationEnabled = TRUE;

	//state->busOffState = g_canBusoff[instance];

	CANInit(instance);
    g_canStatePtr[instance] = state;
}

void mid_can_Deinit(uint8_t instance)
{
	if(instance == CAN0CH)
	{
		PCC-> PCCn[PCC_FlexCAN0_INDEX] &= ~PCC_PCCn_CGC_MASK;   //BUSCLK
		PORTC->PCR[2] = PORT_PCR_MUX(0); /* Port C2: MUX = CAN0_RX,CAN0 RX */
		PORTC->PCR[3] = PORT_PCR_MUX(0); /* Port C3: MUX = CAN0_TX,CAN0 TX */
	
	}
}

/*FUNCTION**********************************************************************
 *
 * Function Name : mid_CanSleep
 * Description   :
 *
 *END**************************************************************************/
void mid_CanSleep( uint8_t instance )
{
	CAN_Type * base = g_canBase[instance];
	can_state_t *canState = g_canStatePtr[instance];

	CANAbortTransfer( instance );
	if(canState->workState != CAN_OPERATING_SLEEP)
	{
		canState->workState = CAN_OPERATING_SLEEP;
		can_log(ELOG_Trace, "[CAN%d]Enter SlepMode!\n", instance);
	}
	CanIf_SetPduMode(CANIF_SET_OFFLINE);
	/*if(instance == CAN0CH)
	{
		CANConfigPN(CAN0CH, &flexcan_cfg_PNConfig);
	}
	else
	{
		CANDisable(base);
	}*/
	CANDisable(base);
}

void mid_CANDisable( uint8_t instance )
{
	CAN_Type * base = g_canBase[instance];

	CANAbortTransfer( instance );
	CANDisable(base);
}

uint8_t CANBusDtcStatus(uint8_t instance)
{	
	return g_canBusoff[instance].DtcStatus;
}
CAN_STATUS CANBusOffStatusDetect(uint8_t instance)
{
	CAN_STATUS res = CAN_NORMAL;
	CAN_Type * base = g_canBase[instance];

	if(base->ESR1 & CAN_ESR1_BOFFINT_MASK)
		res = CAN_BUSOFF;
	else
		res = CAN_NORMAL;
	return res;
}

CAN_STATUS CANBusState(uint8_t instance)
{
	CAN_STATUS ret = CAN_BUSOFF;
	if(instance == CAN0CH)
	{
		ret = g_canBusoff[0].status;
	}
	else if(instance == CAN1CH)
	{
		ret = g_canBusoff[1].status;
	}
	else
	{
	}
	return ret;
}
void Can_CanBusOffParaInit0(void)
{
	g_canBusoff[0].detectTime = 0;
	g_canBusoff[0].timeoutCnt = 0;
	g_canBusoff[0].recoverTimeCnt = 0;
	g_canBusoff[0].swCtrlStep = 1;
	g_canBusoff[0].status = CAN_NORMAL;
	g_canBusoff[0].occurCnt = 0;
}
void Can_CanBusOffParaInit1(void)
{
	g_canBusoff[1].detectTime = 0;
	g_canBusoff[1].timeoutCnt = 0;
	g_canBusoff[1].recoverTimeCnt = 0;
	g_canBusoff[1].swCtrlStep = 1;
	g_canBusoff[1].status = CAN_NORMAL;
	g_canBusoff[1].occurCnt = 0;
}

void Can_CanBusOffTimeCnt(void)
{
	g_canBusoff[0].detectTime++;
	g_canBusoff[0].timeoutCnt++;
	g_canBusoff[0].recoverTimeCnt++;

	g_canBusoff[1].detectTime++;
	g_canBusoff[1].timeoutCnt++;
	g_canBusoff[1].recoverTimeCnt++;
}

void mid_can_busOffProc10ms(uint8_t instance)
{
	CAN_STATUS  canStatusTemp = CAN_NORMAL;
	can_state_t *canState = g_canStatePtr[instance];	
	struct_canMsg_t canPdu = {
						.Id = DMS_1,
						.IdType = CAN_STD_ID,
						.Dlc = 8,
						.Data = {0},
					};	
	uint32_t iflag1 = 0;
	if(instance == CAN0CH) {
		
		iflag1 = CAN0->IFLAG1;
		if(g_canBusoff[0].detectTime >= 1)	{
			g_canBusoff[0].detectTime = 0;
			canStatusTemp = CANBusOffStatusDetect(instance);
			switch(g_canBusoff[0].swCtrlStep)
			{
				case 1:
					if(canStatusTemp == CAN_BUSOFF)
					{
						g_canBusoff[0].status = CAN_BUSOFF;
						g_canBusoff[0].occurCnt++;
						g_canBusoff[0].timeoutCnt = 0;						
						
						can0_State.workState = CAN_OPERATING_UNINIT;
						CAN0->IFLAG1 = iflag1;
						CAN0->CTRL1 |= CAN_CTRL1_BOFFREC_MASK; //disable automatic recovering from bus off
						mid_CANDisable(instance);
						mid_can_Init(instance, &can0_State, &can0_InitConfig);
						CANBusResetEsr(CAN0CH);
						//intcnt = 0;
						canState->txInPtr = 0;
						canState->txOutPtr = 0;
						g_canBusoff[0].recoverTimeCnt = 0;
						g_canBusoff[0].swCtrlStep = 2;
					}
					else
					{
						if(g_canBusoff[0].recoverTimeCnt >= 100)  //100ms
						{
							g_canBusoff[0].recoverTimeCnt = 100;
							g_canBusoff[0].DtcStatus = FALSE;
							g_canBusoff[0].status = CAN_NORMAL;
							g_canBusoff[0].swCtrlStep = 1;
							g_canBusoff[0].occurCnt = 0;
							CAN0->CTRL1 &= ~CAN_CTRL1_BOFFREC_MASK;
						}
					}
					break;
				case 2:
					if(g_canBusoff[0].timeoutCnt >= 95)  //100ms fast recovery
					{
						g_canBusoff[0].timeoutCnt = 0;

						CAN0->CTRL1 &= ~CAN_CTRL1_BOFFREC_MASK;
						//g_canBusoff[0].status = CAN_NORMAL;
						mid_canWrite(CAN0CH, &canPdu);
						mid_canTxService(instance);
						g_canBusoff[0].recoverTimeCnt = 0;

						if(g_canBusoff[0].occurCnt < 5)
						{
							g_canBusoff[0].swCtrlStep = 1;
						}
						else
						{
							g_canBusoff[0].swCtrlStep = 3;
						}
					}
					break;

				case 3:
					if(canStatusTemp == CAN_BUSOFF)
					{
						g_canBusoff[0].status = CAN_BUSOFF;
						g_canBusoff[0].occurCnt++;
						g_canBusoff[0].timeoutCnt = 0;
						can0_State.workState = CAN_OPERATING_UNINIT;
						CAN0->IFLAG1 = iflag1;
						CAN0->CTRL1 |= CAN_CTRL1_BOFFREC_MASK; //disable automatic recovering from bus off
						mid_CANDisable(instance);
						mid_can_Init(instance,&can0_State, &can0_InitConfig);
						CANBusResetEsr(CAN0CH);
						//intcnt = 0;
						canState->txInPtr = 0;
						canState->txOutPtr = 0;
						g_canBusoff[0].swCtrlStep = 4;
						//Mid_Debug_Sprintf("CAN BUS OFF 200ms !\n");
					}
					else
					{
						if(g_canBusoff[0].recoverTimeCnt >= 100)  //100ms
						{
							g_canBusoff[0].recoverTimeCnt = 100;
							g_canBusoff[0].DtcStatus = FALSE;
							g_canBusoff[0].status = CAN_NORMAL;
							g_canBusoff[0].swCtrlStep = 1;
							g_canBusoff[0].occurCnt = 0;
							CAN0->CTRL1 &= ~CAN_CTRL1_BOFFREC_MASK;
						}
					}
					break;

				case 4:
					if(g_canBusoff[0].timeoutCnt >= 1000)  //1000ms slow recovery
					{
						//g_canBusoff[0].status = CAN_NORMAL;
						CAN0->CTRL1 &= ~CAN_CTRL1_BOFFREC_MASK;
						mid_canWrite(CAN0CH, &canPdu);
						mid_canTxService(instance);
						g_canBusoff[0].swCtrlStep = 3;
						g_canBusoff[0].recoverTimeCnt = 0;
					}
					break;
					
				default:
					Can_CanBusOffParaInit0();
					break;
			}
			if(g_canBusoff[0].occurCnt >= 5)
			{
				g_canBusoff[0].occurCnt = 5;
				g_canBusoff[0].DtcStatus = TRUE;
			}
		}
	}
	else
	{
	}
}


static void TCAN1043_Delay(uint16_t num)
{
    while(num--);
}
void TCAN1043_OperatingMode (CanIf_ControllerModeType mode)
{
	CAN0_STB_OUTPUT;
	CAN0_WAKE_OUTPUT;
	CAN0_EN_OUTPUT;
    switch(mode)
    {
        case CANIF_CS_STARTED :
            CAN0_WAKE_EN;    //WAKE=1  
            TCAN1043_Delay(700);
            CAN0_WAKE_DIS;    //WAKE=0
            CAN0_EN_EN;      //EN=1
            CAN0_STB_EN;     //STB=1 
            break;
        
        case CANIF_CS_SLEEP :
            CAN0_STB_DIS;     //STB=0 
            CAN0_EN_EN;      //EN=1 
            TCAN1043_Delay(700);
            CAN0_EN_DIS;      //EN=0
			CAN0_WAKE_DIS;
            break;
        default :
            break;
    }
}





